/**
 * Copyright (c) 2012, http://www.yissugames.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yissugames.gui;

import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.util.Rectangle;
import org.newdawn.slick.Color;
import org.newdawn.slick.TrueTypeFont;
import org.newdawn.slick.opengl.Texture;

import com.yissugames.blocklife.BlockLife;
import com.yissugames.blocklife.ContentLoader;
import com.yissugames.blocklife.Language;
import com.yissugames.blocklife.RenderSystem;
import com.yissugames.blocklife.Screen;

public abstract class XMLScreen implements Screen {

	private String[] menuPoints;
	private int[] menuFunctionId;
	private TrueTypeFont menuFont;
	private int menuPosX = -1;
	private int menuPosY = -1;
	
	private Texture background = null;
	
	private ArrayList<Object> objects = new ArrayList<Object>();
	private ArrayList<HashMap<String, Object>> buttons = new ArrayList<HashMap<String, Object>>();
	
	private boolean refresh;
	
	private String asset;
	
	public XMLScreen(String asset)
	{
		this.asset = asset;
		loadXml(asset);
	}
	
	public Object getObjectByTypeAndId(GUIType type, int id)
	{
		int i = 0;
		
		for(Object obj: objects)
		{
			if(isObjectGUIType(obj, type))
			{
				if(i == id)
					return obj;
				i++;
			}
		}
		
		return null;
	}
	
	private boolean isObjectGUIType(Object object, GUIType type)
	{
		switch(type)
		{
		case Button:
			return object instanceof Button;
		case CheckBox:
			return object instanceof CheckBox;
		case ComboBox:
			return object instanceof ComboBox;
		case Image:
			return object instanceof Image;
		case Label:
			return object instanceof Label;
		case Slider:
			return object instanceof Slider;
		case TextBox:
			return object instanceof TextBox;
		default:
			return false;
		}
	}
	
	private void loadXml(String asset)
	{
		objects = new ArrayList<Object>();
		menuPoints = null;
		menuFunctionId = null;
		menuPosX = -1;
		menuPosY = -1;
		background = null;
		
		File file = new File("res/menus/" + asset + ".xml");
		
		try {
			SAXBuilder builder = new SAXBuilder();
			Document doc = builder.build(file);
			
			Element root = doc.getRootElement();
			if(root.getAttributeValue("background") != "null")
				background = ContentLoader.getTexture(root.getAttributeValue("background"));
			
			List<Element> childElements = root.getChildren();
			for(Element e: childElements)
			{
				if(e.getName() == "menu")
				{
					menuFont = ContentLoader.getFont(e.getAttributeValue("fontname"), Font.BOLD, Integer.parseInt(e.getAttributeValue("fontsize")));
					menuPoints = new String[e.getChildren("menuPoint").size()];
					menuFunctionId = new int[e.getChildren("menuPoint").size()];
					
					if(!e.getAttributeValue("positionX").equals("center"))
						menuPosX = Integer.parseInt(e.getAttributeValue("positionX"));
					if(!e.getAttributeValue("positionY").equals("center"))
						menuPosY = Integer.parseInt(e.getAttributeValue("positionY"));
					
					int i = 0;
					for(Element e2: e.getChildren("menuPoint"))
					{
						menuPoints[i] = e2.getText();
						menuFunctionId[i] = Integer.parseInt(e2.getAttributeValue("functionId"));
						i++;
					}
				}
				if(e.getName() == "image")
				{
					int posX = -1;
					if(!e.getAttributeValue("positionX").equals("center"))
						posX = Integer.parseInt(e.getAttributeValue("positionX"));
					int posY = -1;
					if(!e.getAttributeValue("positionY").equals("center"))
						posY = Integer.parseInt(e.getAttributeValue("positionY"));
					objects.add(new Image(e.getAttributeValue("file"), posX, posY));
				}
				if(e.getName() == "label")
				{
					int posX = -1;
					if(!e.getAttributeValue("positionX").equals("center"))
						posX = Integer.parseInt(e.getAttributeValue("positionX"));
					int posY = -1;
					if(!e.getAttributeValue("positionY").equals("center") && !e.getAttributeValue("positionY").equals("bottom"))
						posY = Integer.parseInt(e.getAttributeValue("positionY"));
					if(e.getAttributeValue("positionY").equals("bottom"))
						posY = -2;
					int style = 0;
					if(e.getAttributeValue("style") != null)
						style = Integer.parseInt(e.getAttributeValue("style"));
					objects.add(new Label(e.getAttributeValue("fontname"), Integer.parseInt(e.getAttributeValue("fontsize")), style, e.getAttributeValue("color"), e.getText(), posX, posY));
				}
				if(e.getName() == "textbox")
					objects.add(TextBox.createByXML(e));
				if(e.getName() == "combobox")
					objects.add(ComboBox.createByXML(e));
				if(e.getName() == "checkbox")
					objects.add(CheckBox.createByXML(e));
				if(e.getName() == "button")
				{
					objects.add(Button.createByXML(e));
					HashMap<String, Object> hmap = new HashMap<String, Object>();
					hmap.put("object", objects.get(objects.size() - 1));
					hmap.put("id", e.getAttributeValue("id"));
					buttons.add(hmap);
				}
				if(e.getName() == "animatedimage")
					objects.add(AnimatedImage.createByXML(e));
			}
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public Button getButton(String id)
	{
		for(HashMap<String, Object> hmap: buttons)
			if(hmap.get("id").equals(id))
				return (Button) hmap.get("object");
		
		return null;
	}
	
	@Override
	public void render() {
		if(background != null)
			RenderSystem.renderTexture(background, 0, 0);
		
		if(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && Keyboard.isKeyDown(Keyboard.KEY_F5) && !refresh)
		{
			loadXml(asset);
			refresh = true;
		} else if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || !Keyboard.isKeyDown(Keyboard.KEY_F5))
			refresh = false;
		
		while(Keyboard.next())
			for(Object obj: objects)
				if(obj instanceof Inputable)
					((Inputable) obj).sendInput(Keyboard.getEventCharacter());
		
		for(Object obj: objects)
			if(obj instanceof GUI)
				((GUI) obj).render();
		
		if(menuPoints != null)
		{
			int neededHeight = (menuFont.getLineHeight() + 5) * menuPoints.length;
			int firstPosY = BlockLife.DisplayHeight / 2 - neededHeight / 2;
			if(menuPosY != -1)
				firstPosY = menuPosY;
			
			for(int i = 0; i < menuPoints.length; i++)
			{	
				String str = Language.getValueAsString(menuPoints[i]);
				
				int posX = BlockLife.DisplayWidth / 2 - menuFont.getWidth(str) / 2;
				if(menuPosX != -1)
					posX = menuPosX;
				
				int posY = firstPosY + (menuFont.getLineHeight() + 5) * i;
				
				Rectangle rect = new Rectangle(posX, posY, menuFont.getWidth(str), menuFont.getLineHeight());
				
				boolean hoverd = false;
				if(rect.contains(Mouse.getX(), BlockLife.DisplayHeight - Mouse.getY() - 1))
				{
					hoverd = true;
					posX = BlockLife.DisplayWidth / 2 - menuFont.getWidth(str) / 2 - menuFont.getWidth(">");
					
					if(Mouse.isButtonDown(0))
					{
						onClick(menuFunctionId[i]);
					}
				}
				
				menuFont.drawString(posX, posY, hoverd ? ">" + str : str, Color.black);
			}
		}
		
		specialRender();
	}
	
	public abstract void onClick(int i);
	
	public abstract void specialRender();
	
	public abstract boolean specialInit();

	@Override
	public boolean init() {
		return specialInit();
	}

	@Override
	public boolean quit() {
		// TODO Auto-generated method stub
		return true;
	}
	
	public enum GUIType
	{
		Button, CheckBox, ComboBox, Image, Label, Slider, TextBox
	}

}
